/**
 * 通用JavaScript日志系统
 * 支持所有JavaScript环境：浏览器、Node.js、React Native、小程序等
 */

class UniversalLogger {
  constructor(config = {}) {
    this.config = {
      serverUrl: config.serverUrl || this._getDefaultServerUrl(),
      enableRemoteLogging: config.enableRemoteLogging !== false,
      enableConsoleLogging: config.enableConsoleLogging !== false,
      maxLocalLogs: config.maxLocalLogs || 1000,
      autoSendInterval: config.autoSendInterval || 0,
      ...config,
    }

    this.logs = []
    this.networkLogs = []
    this.isConnected = false
    this.sendQueue = []
    this.environment = this._detectEnvironment()

    // 初始化网络拦截器
    this._initNetworkInterceptors()

    // 初始化自动发送
    if (this.config.autoSendInterval > 0) {
      this._setupAutoSend()
    }
  }

  /**
   * 检测运行环境
   */
  _detectEnvironment() {
    // 检测React Native
    if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
      return 'react-native'
    }

    // 检测Node.js
    if (typeof process !== 'undefined' && process.versions && process.versions.node) {
      return 'node'
    }

    // 检测微信小程序
    if (typeof wx !== 'undefined' && wx.getSystemInfo) {
      return 'wechat-miniprogram'
    }

    // 检测支付宝小程序
    if (typeof my !== 'undefined' && my.getSystemInfo) {
      return 'alipay-miniprogram'
    }

    // 检测浏览器
    if (typeof window !== 'undefined' && typeof document !== 'undefined') {
      return 'browser'
    }

    return 'unknown'
  }

  /**
   * 获取默认服务器URL
   */
  _getDefaultServerUrl() {
    if (this.environment === 'browser') {
      return `${window.location.protocol}//${window.location.hostname}:3000`
    }
    return 'http://localhost:3000'
  }

  /**
   * 初始化网络拦截器
   */
  _initNetworkInterceptors() {
    this._interceptFetch()
    this._interceptXHR()
    this._interceptAxios()
  }

  /**
   * 拦截fetch请求
   */
  _interceptFetch() {
    if (typeof fetch === 'undefined') return

    const originalFetch = fetch
    const self = this

    fetch = function (...args) {
      const startTime = Date.now()
      const [url, options = {}] = args

      const requestData = {
        id: self._generateId(),
        type: 'fetch',
        url: url.toString(),
        method: options.method || 'GET',
        headers: options.headers || {},
        body: options.body,
        startTime,
        timestamp: new Date().toISOString(),
      }

      return originalFetch
        .apply(this, args)
        .then((response) => {
          const endTime = Date.now()
          const duration = endTime - startTime

          // 克隆响应以读取body
          const responseClone = response.clone()

          responseClone
            .text()
            .then((responseText) => {
              let responseData
              try {
                responseData = JSON.parse(responseText)
              } catch (e) {
                responseData = responseText
              }

              const networkLog = {
                ...requestData,
                status: response.status,
                statusText: response.statusText,
                responseHeaders: self._getResponseHeaders(response),
                responseData,
                duration,
                endTime,
                success: response.ok,
              }

              self._addNetworkLog(networkLog)
            })
            .catch(() => {
              // 处理读取响应失败的情况
              const networkLog = {
                ...requestData,
                status: response.status,
                statusText: response.statusText,
                responseHeaders: self._getResponseHeaders(response),
                responseData: 'Unable to read response',
                duration,
                endTime,
                success: response.ok,
              }

              self._addNetworkLog(networkLog)
            })

          return response
        })
        .catch((error) => {
          const endTime = Date.now()
          const duration = endTime - startTime

          const networkLog = {
            ...requestData,
            status: 0,
            statusText: 'Network Error',
            responseHeaders: {},
            responseData: error.message,
            duration,
            endTime,
            success: false,
            error: error.message,
          }

          self._addNetworkLog(networkLog)
          throw error
        })
    }
  }

  /**
   * 拦截XMLHttpRequest
   */
  _interceptXHR() {
    if (typeof XMLHttpRequest === 'undefined') return

    const originalXHR = XMLHttpRequest
    const self = this

    XMLHttpRequest = function () {
      const xhr = new originalXHR()
      const startTime = Date.now()
      let requestData = {
        id: self._generateId(),
        type: 'xhr',
        url: '',
        method: 'GET',
        headers: {},
        body: null,
        startTime,
        timestamp: new Date().toISOString(),
      }

      // 拦截open方法
      const originalOpen = xhr.open
      xhr.open = function (method, url, ...args) {
        requestData.method = method.toUpperCase()
        requestData.url = url.toString()
        return originalOpen.apply(this, [method, url, ...args])
      }

      // 拦截setRequestHeader方法
      const originalSetRequestHeader = xhr.setRequestHeader
      xhr.setRequestHeader = function (name, value) {
        requestData.headers[name] = value
        return originalSetRequestHeader.apply(this, [name, value])
      }

      // 拦截send方法
      const originalSend = xhr.send
      xhr.send = function (body) {
        requestData.body = body

        xhr.addEventListener('loadend', function () {
          const endTime = Date.now()
          const duration = endTime - startTime

          let responseData
          try {
            responseData = JSON.parse(xhr.responseText)
          } catch (e) {
            responseData = xhr.responseText
          }

          const networkLog = {
            ...requestData,
            status: xhr.status,
            statusText: xhr.statusText,
            responseHeaders: self._parseResponseHeaders(xhr.getAllResponseHeaders()),
            responseData,
            duration,
            endTime,
            success: xhr.status >= 200 && xhr.status < 300,
          }

          self._addNetworkLog(networkLog)
        })

        return originalSend.apply(this, [body])
      }

      return xhr
    }

    // 保持原型链
    XMLHttpRequest.prototype = originalXHR.prototype
  }

  /**
   * 拦截Axios（如果存在）
   */
  _interceptAxios() {
    // 延迟检查axios，因为它可能在后面才加载
    setTimeout(() => {
      if (typeof axios !== 'undefined') {
        this._setupAxiosInterceptors()
      }

      // 检查全局window.axios
      if (typeof window !== 'undefined' && window.axios) {
        this._setupAxiosInterceptors(window.axios)
      }
    }, 100)
  }

  /**
   * 设置Axios拦截器
   */
  _setupAxiosInterceptors(axiosInstance = axios) {
    const self = this

    // 请求拦截器
    axiosInstance.interceptors.request.use(
      (config) => {
        config.metadata = {
          id: self._generateId(),
          startTime: Date.now(),
          timestamp: new Date().toISOString(),
        }
        return config
      },
      (error) => {
        return Promise.reject(error)
      },
    )

    // 响应拦截器
    axiosInstance.interceptors.response.use(
      (response) => {
        const endTime = Date.now()
        const config = response.config
        const duration = endTime - config.metadata.startTime

        const networkLog = {
          id: config.metadata.id,
          type: 'axios',
          url: config.url,
          method: (config.method || 'get').toUpperCase(),
          headers: config.headers || {},
          body: config.data,
          status: response.status,
          statusText: response.statusText,
          responseHeaders: response.headers || {},
          responseData: response.data,
          duration,
          startTime: config.metadata.startTime,
          endTime,
          timestamp: config.metadata.timestamp,
          success: true,
        }

        self._addNetworkLog(networkLog)
        return response
      },
      (error) => {
        const endTime = Date.now()
        const config = error.config || {}
        const duration = config.metadata ? endTime - config.metadata.startTime : 0

        const networkLog = {
          id: config.metadata ? config.metadata.id : self._generateId(),
          type: 'axios',
          url: config.url || 'unknown',
          method: (config.method || 'get').toUpperCase(),
          headers: config.headers || {},
          body: config.data,
          status: error.response ? error.response.status : 0,
          statusText: error.response ? error.response.statusText : 'Network Error',
          responseHeaders: error.response ? error.response.headers : {},
          responseData: error.response ? error.response.data : error.message,
          duration,
          startTime: config.metadata ? config.metadata.startTime : endTime,
          endTime,
          timestamp: config.metadata ? config.metadata.timestamp : new Date().toISOString(),
          success: false,
          error: error.message,
        }

        self._addNetworkLog(networkLog)
        return Promise.reject(error)
      },
    )
  }

  /**
   * 生成唯一ID
   */
  _generateId() {
    return Date.now().toString(36) + Math.random().toString(36).substr(2)
  }

  /**
   * 获取响应头
   */
  _getResponseHeaders(response) {
    const headers = {}
    if (response.headers && response.headers.forEach) {
      response.headers.forEach((value, key) => {
        headers[key] = value
      })
    }
    return headers
  }

  /**
   * 解析响应头字符串
   */
  _parseResponseHeaders(headerStr) {
    const headers = {}
    if (!headerStr) return headers

    headerStr.split('\r\n').forEach((line) => {
      const parts = line.split(': ')
      if (parts.length === 2) {
        headers[parts[0]] = parts[1]
      }
    })
    return headers
  }

  /**
   * 添加网络日志
   */
  _addNetworkLog(networkLog) {
    this.networkLogs.push(networkLog)

    // 限制网络日志数量
    if (this.networkLogs.length > this.config.maxLocalLogs) {
      this.networkLogs = this.networkLogs.slice(-this.config.maxLocalLogs)
    }

    // 发送到远程服务器
    if (this.config.enableRemoteLogging) {
      this._sendToServer({
        type: 'network',
        timestamp: Date.now().toString(),
        data: networkLog,
      })
    }
  }

  /**
   * 设置自动发送
   */
  _setupAutoSend() {
    setInterval(() => {
      if (this.sendQueue.length > 0) {
        this._processSendQueue()
      }
    }, this.config.autoSendInterval)
  }

  /**
   * 处理发送队列
   */
  async _processSendQueue() {
    if (this.sendQueue.length === 0) return

    const batch = [...this.sendQueue]
    this.sendQueue = []

    try {
      await Promise.all(batch.map((data) => this._sendToServer(data)))
    } catch (error) {
      // 发送失败，重新加入队列
      this.sendQueue.unshift(...batch)
    }
  }

  /**
   * 发送数据到服务器
   */
  async _sendToServer(data) {
    if (!this.config.enableRemoteLogging) return

    try {
      const response = await this._makeRequest('/api/log', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(data),
      })

      this.isConnected = true
      return response
    } catch (error) {
      this.isConnected = false

      if (this.config.autoSendInterval > 0) {
        this.sendQueue.push(data)
      }

      throw error
    }
  }

  /**
   * 通用请求方法
   */
  async _makeRequest(endpoint, options) {
    const url = `${this.config.serverUrl}${endpoint}`

    if (this.environment === 'wechat-miniprogram') {
      return new Promise((resolve, reject) => {
        wx.request({
          url,
          method: options.method || 'GET',
          data: options.body ? JSON.parse(options.body) : undefined,
          header: options.headers,
          success: resolve,
          fail: reject,
        })
      })
    }

    if (this.environment === 'alipay-miniprogram') {
      return new Promise((resolve, reject) => {
        my.request({
          url,
          method: options.method || 'GET',
          data: options.body ? JSON.parse(options.body) : undefined,
          headers: options.headers,
          success: resolve,
          fail: reject,
        })
      })
    }

    // 使用fetch（浏览器、React Native、Node.js）
    if (typeof fetch !== 'undefined') {
      const response = await fetch(url, options)
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`)
      }
      return response.json()
    }

    throw new Error('No request method available')
  }

  /**
   * 格式化日志消息
   */
  _formatMessage(level, messages) {
    return {
      id: this._generateId(),
      timestamp: Date.now().toString(),
      level,
      environment: this.environment,
      userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'Unknown',
      message: messages.map((msg) => {
        if (typeof msg === 'object') {
          try {
            return JSON.stringify(msg, null, 2)
          } catch (e) {
            return String(msg)
          }
        }
        return String(msg)
      }),
    }
  }

  /**
   * 存储本地日志
   */
  _storeLocalLog(logData) {
    this.logs.push(logData)

    // 限制本地日志数量
    if (this.logs.length > this.config.maxLocalLogs) {
      this.logs = this.logs.slice(-this.config.maxLocalLogs)
    }
  }

  /**
   * 通用日志方法
   */
  async _log(level, ...messages) {
    const logData = this._formatMessage(level, messages)

    // 存储本地日志
    this._storeLocalLog(logData)

    // 控制台输出
    if (this.config.enableConsoleLogging && typeof console !== 'undefined') {
      const consoleMethod = console[level] || console.log
      consoleMethod(`[${level.toUpperCase()}]`, ...messages)
    }

    // 远程发送
    if (this.config.enableRemoteLogging) {
      const sendData = {
        type: 'log',
        timestamp: logData.timestamp,
        data: logData,
      }

      if (this.config.autoSendInterval > 0) {
        this.sendQueue.push(sendData)
      } else {
        try {
          await this._sendToServer(sendData)
        } catch (error) {
          // 静默处理发送错误
        }
      }
    }

    return logData
  }

  // 日志级别方法
  debug(...messages) {
    return this._log('debug', ...messages)
  }
  info(...messages) {
    return this._log('info', ...messages)
  }
  log(...messages) {
    return this._log('log', ...messages)
  }
  warn(...messages) {
    return this._log('warn', ...messages)
  }
  error(...messages) {
    return this._log('error', ...messages)
  }

  // 清空方法
  async clear() {
    try {
      await this._sendToServer({
        type: 'clear',
        timestamp: Date.now().toString(),
        data: { action: 'clear' },
      })
    } catch (error) {
      // 静默处理
    }
  }

  clearLocal() {
    this.logs = []
    this.networkLogs = []
  }

  // 获取数据方法
  getLogs(level = null) {
    if (level) {
      return this.logs.filter((log) => log.level === level)
    }
    return [...this.logs]
  }

  getNetworkLogs() {
    return [...this.networkLogs]
  }

  getConnectionStatus() {
    return {
      isConnected: this.isConnected,
      environment: this.environment,
      queueLength: this.sendQueue.length,
      logsCount: this.logs.length,
      networkLogsCount: this.networkLogs.length,
    }
  }

  // 配置方法
  updateConfig(newConfig) {
    this.config = { ...this.config, ...newConfig }
  }

  async flush() {
    await this._processSendQueue()
  }
}

export default UniversalLogger


